﻿package yii.base{

	import yii.*;
	import phpas3.*;
	import yii.collections.*;

	public class CModule{

	/**
	 * @var array the IDs of the application components that should be preloaded+
	 */
	public var preload=new Array();
	/**
	 * @var array the behaviors that should be attached to the module+
	 * The behaviors will be attached to the module when {@link init} is called+
	 * Please refer to {@link CModel::behaviors} on how to specify the value of this property+
	 */
	public var behaviors=new Array();

	private var _id;
	private var _parentModule;
	private var _basePath;
	private var _modulePath;
	private var _params;
	private var _modules=new Array();
	private var _moduleConfig=new Array();
	private var _components=new Array();
	private var _componentConfig=new Array();

	public function set components( $components:Object ):void{
		this.setComponents( $components );
	}
	public function get components():Object{
		return this.getComponents();
	}





	/**
	 * Returns the application components+
	 * @param boolean $loadedOnly whether to return the loaded components only+ If this is set false,
	 * then all components specified in the configuration will be returned, whether they are loaded or not+
	 * Loaded components will be returned as objects, while unloaded components as configuration arrays+
	 * This parameter has been available since version 1+1+3+
	 * @return array the application components (indexed by their IDs)
	 */
	public function getComponents($loadedOnly:Boolean=true):Object{
		if($loadedOnly)
			return this._components;
		else
			return array_merge(this._componentConfig, this._components);
	}

	/**
	 * Puts a component under the management of the module+
	 * The component will be initialized by calling its {@link CApplicationComponent::init() init()}
	 * method if it has not done so+
	 * @param string $id component ID
	 * @param IApplicationComponent $component the component to be added to the module+
	 * If this parameter is null, it will unload the component from the module+
	 */
	public function setComponent( $id:String, $component:IApplicationComponent ):void{
		if($component===null){
			delete this._components[$id];
		} else {
			this._components[$id]=$component;
			if(!$component.getIsInitialized())
				$component.init();
		}
	}





	/**
	 * Sets the application components+
	 *
	 * When a configuration is used to specify a component, it should consist of
	 * the component's initial property values (name-value pairs)+ Additionally,
	 * a component can be enabled (default) or disabled by specifying the 'enabled' value
	 * in the configuration+
	 *
	 * If a configuration is specified with an ID that is the same as an existing
	 * component or configuration, the existing one will be replaced silently+
	 *
	 * The following is the configuration for two components:
	 * <pre>
	 * array(
	 *     'db'=>array(
	 *         'class'=>'CDbConnection',
	 *         'connectionString'=>'sqlite:path/to/file+db',
	 *     ),
	 *     'cache'=>array(
	 *         'class'=>'CDbCache',
	 *         'connectionID'=>'db',
	 *         'enabled'=>!YII_DEBUG,  // enable caching in non-debug mode
	 *     ),
	 * )
	 * </pre>
	 *
	 * @param array $components application components(id=>component configuration or instances)
	 * @param boolean $merge whether to merge the new component configuration with the existing one+
	 * Defaults to true, meaning the previously registered component configuration of the same ID
	 * will be merged with the new configuration+ If false, the existing configuration will be replaced completely+
	 */
	public function setComponents( $components:Object,$merge:Boolean=true ):void{
		for( var $id in $components ){
			var $component = $components[$id];
			if( $component is IApplicationComponent )
				this.setComponent($id,$component);
			else if(isset(this._componentConfig[$id]) && $merge)
				this._componentConfig[$id] = CMap.mergeArray( this._componentConfig[$id], $component );
			else
				this._componentConfig[$id] = $component;
		}
	}





	/**
	 * Initializes the module+
	 * This method is called at the end of the module constructor+
	 * Note that at this moment, the module has been configured, the behaviors
	 * have been attached and the application components have been registered+
	 * @see preinit
	 */
	protected function init(){
	}


	/**
	 * Loads static application components+
	 */
	protected function preloadComponents():void{
		for( var index in this.preload ){
			var $id = this.preload[index];
			this.getComponent($id);
		}
	}


	/**
	 * Configures the module with the specified configuration+
	 * @param array $config the configuration array
	 */
	public function configure($config:Object):void{
		for( var $key in $config ){
			var $value = $config[$key];
			this[$key] = $value;
		}
	}




	/**
	 * Preinitializes the module+
	 * This method is called at the beginning of the module constructor+
	 * You may override this method to do some customized preinitialization work+
	 * Note that at this moment, the module is not configured yet+
	 * @see init
	 */
	protected function preinit(){
	}


	/**
	 * Retrieves the named application component+
	 * @param string $id application component ID (case-sensitive)
	 * @param boolean $createIfNull whether to create the component if it doesn't exist yet+ This parameter
	 * has been available since version 1+0+6+
	 * @return IApplicationComponent the application component instance, null if the application component is disabled or does not exist+
	 * @see hasComponent
	 */
	public function getComponent( $id:String, $createIfNull:Boolean=true ){
		if(isset(this._components[$id])){
			return this._components[$id];
		} else if(isset(this._componentConfig[$id]) && $createIfNull){
			var $config = this._componentConfig[$id];
			if( !isset($config['enabled']) || $config['enabled'] ){
				Yii.log("Loading 「"+ $id +"」 application component",'system.CModule');
				delete $config['enabled'];
				var $component = Yii.createComponent($config);
				$component.init();
				return this._components[$id] = $component;
			}
		}
	}


	}
}